"""
AST基础类定义

定义抽象语法树的基础类和接口。
"""

from abc import ABC, abstractmethod
from typing import Any, Dict, List, Optional, Type, TypeVar, Union
from dataclasses import dataclass, field
from enum import Enum
import uuid

# 类型变量
T = TypeVar('T', bound='Ast')


class AstNodeType(Enum):
    """AST节点类型枚举"""
    
    # 基础控制节点
    SEQUENCE = "sequence"
    PARALLEL = "parallel"
    CONDITIONAL = "conditional"
    LOOP = "loop"
    
    # 视频处理节点
    FFMPEG_SLICE = "ffmpeg_slice"
    EXTRACT_METADATA = "extract_metadata"
    SCAN_DIRECTORY = "scan_directory"
    
    # AI分类节点
    GEMINI_CLASSIFY = "gemini_classify"
    
    # 输出节点
    OUTPUT_DRAFT = "output_draft"
    ORGANIZE_FILES = "organize_files"
    GENERATE_REPORT = "generate_report"
    
    # 工具节点
    FILE_OPERATION = "file_operation"
    DATA_TRANSFORM = "data_transform"


class AstNodeStatus(Enum):
    """AST节点状态枚举"""
    
    PENDING = "pending"      # 等待执行
    RUNNING = "running"      # 正在执行
    COMPLETED = "completed"  # 执行完成
    FAILED = "failed"        # 执行失败
    SKIPPED = "skipped"      # 跳过执行


@dataclass
class AstContext:
    """AST执行上下文"""
    
    # 执行环境信息
    execution_id: str = field(default_factory=lambda: str(uuid.uuid4()))
    workspace_path: str = ""
    temp_path: str = ""
    
    # 数据传递
    data: Dict[str, Any] = field(default_factory=dict)
    variables: Dict[str, Any] = field(default_factory=dict)
    
    # 执行状态
    current_node: Optional['Ast'] = None
    error_info: Optional[Dict[str, Any]] = None
    
    # 配置信息
    config: Dict[str, Any] = field(default_factory=dict)
    
    def get_variable(self, name: str, default: Any = None) -> Any:
        """获取变量值"""
        return self.variables.get(name, default)
    
    def set_variable(self, name: str, value: Any) -> None:
        """设置变量值"""
        self.variables[name] = value
    
    def get_data(self, key: str, default: Any = None) -> Any:
        """获取数据"""
        return self.data.get(key, default)
    
    def set_data(self, key: str, value: Any) -> None:
        """设置数据"""
        self.data[key] = value


class Ast(ABC):
    """
    抽象语法树基类
    
    所有AST节点都必须继承此类并实现相应的方法。
    """
    
    def __init__(
        self,
        node_id: Optional[str] = None,
        name: Optional[str] = None,
        description: Optional[str] = None,
        **kwargs
    ):
        self.node_id = node_id or str(uuid.uuid4())
        self.name = name or self.__class__.__name__
        self.description = description or ""
        self.status = AstNodeStatus.PENDING
        self.metadata: Dict[str, Any] = kwargs
        
        # 执行统计
        self.start_time: Optional[float] = None
        self.end_time: Optional[float] = None
        self.error: Optional[Exception] = None
    
    @property
    @abstractmethod
    def node_type(self) -> AstNodeType:
        """返回节点类型"""
        pass
    
    @abstractmethod
    def accept(self, visitor: 'AstVisitor', context: AstContext) -> Any:
        """接受访问者访问"""
        pass
    
    def validate(self) -> List[str]:
        """
        验证节点配置
        
        Returns:
            错误信息列表，空列表表示验证通过
        """
        errors = []
        
        # 基础验证
        if not self.node_id:
            errors.append("节点ID不能为空")
        
        if not self.name:
            errors.append("节点名称不能为空")
        
        return errors
    
    def clone(self: T) -> T:
        """克隆节点"""
        # 创建新的节点实例
        new_node = self.__class__(**self.metadata)
        new_node.name = self.name
        new_node.description = self.description
        new_node.node_id = str(uuid.uuid4())  # 生成新的ID
        
        return new_node
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        return {
            "node_id": self.node_id,
            "node_type": self.node_type.value,
            "name": self.name,
            "description": self.description,
            "status": self.status.value,
            "metadata": self.metadata,
        }
    
    @classmethod
    def from_dict(cls, data: Dict[str, Any]) -> 'Ast':
        """从字典创建节点"""
        # 这是一个基础实现，子类应该重写此方法
        node = cls(**data.get("metadata", {}))
        node.node_id = data.get("node_id", str(uuid.uuid4()))
        node.name = data.get("name", cls.__name__)
        node.description = data.get("description", "")
        
        return node
    
    def __str__(self) -> str:
        return f"{self.__class__.__name__}(id={self.node_id[:8]}, name={self.name})"
    
    def __repr__(self) -> str:
        return self.__str__()


class AstNode(Ast):
    """
    具体AST节点基类
    
    为具体的AST节点提供通用功能。
    """
    
    def __init__(
        self,
        inputs: Optional[Dict[str, Any]] = None,
        outputs: Optional[Dict[str, Any]] = None,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.inputs = inputs or {}
        self.outputs = outputs or {}
    
    def get_input(self, name: str, default: Any = None) -> Any:
        """获取输入参数"""
        return self.inputs.get(name, default)
    
    def set_input(self, name: str, value: Any) -> None:
        """设置输入参数"""
        self.inputs[name] = value
    
    def get_output(self, name: str, default: Any = None) -> Any:
        """获取输出结果"""
        return self.outputs.get(name, default)
    
    def set_output(self, name: str, value: Any) -> None:
        """设置输出结果"""
        self.outputs[name] = value
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        data = super().to_dict()
        data.update({
            "inputs": self.inputs,
            "outputs": self.outputs,
        })
        return data


class CompositeAst(Ast):
    """
    复合AST节点基类
    
    包含子节点的AST节点。
    """
    
    def __init__(
        self,
        children: Optional[List[Ast]] = None,
        **kwargs
    ):
        super().__init__(**kwargs)
        self.children = children or []
    
    def add_child(self, child: Ast) -> None:
        """添加子节点"""
        self.children.append(child)
    
    def remove_child(self, child: Ast) -> bool:
        """移除子节点"""
        try:
            self.children.remove(child)
            return True
        except ValueError:
            return False
    
    def get_children(self) -> List[Ast]:
        """获取所有子节点"""
        return self.children.copy()
    
    def validate(self) -> List[str]:
        """验证节点及其子节点"""
        errors = super().validate()
        
        # 验证子节点
        for i, child in enumerate(self.children):
            child_errors = child.validate()
            for error in child_errors:
                errors.append(f"子节点[{i}]: {error}")
        
        return errors
    
    def to_dict(self) -> Dict[str, Any]:
        """转换为字典"""
        data = super().to_dict()
        data["children"] = [child.to_dict() for child in self.children]
        return data
